#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
# 文件: main.py
# 说明: 
# 时间: 2021/08/19 21:39:33
# 作者: Azure
# 版本: 1.0

import json
import os
import re
import sys
import time
from typing import Any, Dict, List, Union

from msedge.selenium_tools import Edge, EdgeOptions
from selenium.webdriver.remote.webelement import WebElement

os.chdir(sys.path[0])

def main():
    '''main'''
    a = TjuEducation()
    a.test()

class TjuEducation(object):
    '''天津大学入学教育自动化'''
    __baseurl = 'http://coursera.twt.edu.cn'        # 主页
    __loginurl = 'http://coursera.twt.edu.cn/login' # 登录页面
    __learnurl = 'http://coursera.twt.edu.cn/my/courses/learning'   # 课程界面

    def __init__(self) -> None:
        # 读取配置文件
        self.__config = json.load(open('config.json', 'r', encoding='utf-8'))
        # 初始化浏览器配置
        edge_options = EdgeOptions()
        edge_options.use_chromium = True
        edge_options.add_experimental_option('excludeSwitches', ['enable-logging']) # 禁用日志打印
        # edge_options.add_argument('--headless')     # 设置无头属性
        edge_options.add_argument('--disable-gpu')  # 禁用gpu
        prefs = {"profile.managed_default_content_settings.images": 2}
        edge_options.add_experimental_option("prefs", prefs)    # 设置无图
        # 浏览器驱动初始化
        self.__edge = Edge(executable_path='edgedriver_win64\msedgedriver.exe', options=edge_options)
        self.__edge.implicitly_wait(5)  # 设置隐式等待时间

    @property
    def config(self) -> Dict[str, Any]: # 配置文件
        return self.__config
    
    @property
    def edge(self):                     # 浏览器驱动
        return self.__edge
    
    def __updatejson(self, ignoreurl:str) -> List[str]:
        '''本地保存排除列表(url)'''
        try:
            localdata = json.load(open('ignore.json', encoding='utf-8'))
        except:
            localdata = []
        localdata:List[str]
        localdata.append(ignoreurl)
        json.dump(localdata, open('ignore.json', 'w', encoding='utf-8'), indent=4, ensure_ascii=False)
        return localdata

    def __readjson(self):
        try:
            localdata:List[str] = json.load(open('ignore.json', encoding='utf-8'))
        except:
            localdata = self.__updatejson('忽略课程列表')
        return localdata

    def __login(self):
        '''登录账号'''
        name = self.config['name']  # 登陆账号
        pwd = self.config['pwd']    # 登录密码
        self.edge.get(self.__loginurl)  # 打开登录网页
        namebox:WebElement = self.edge.find_element_by_xpath('//input[@id="login_username"]')   # 学号输入框
        namebox.clear()
        namebox.send_keys(name) # 输入学号
        pwdbox:WebElement = self.edge.find_element_by_xpath('//input[@id="login_password"]')    # 密码输入框
        pwdbox.clear()
        pwdbox.send_keys(pwd)   # 输入密码
        loginbox:WebElement = self.edge.find_element_by_xpath('//button[text()="登录"]')        # 登录按钮
        loginbox.click()        # 点击登录按钮

    def __findcourse(self):
        '''寻找首页中的可用课程'''
        self.edge.get(self.__learnurl)  # 打开学习页面
        while True:
            # 寻找这个页面中所有的课程
            allcourse:List[WebElement] = self.edge.find_elements_by_xpath('//a[text()="继续学习"]')
            ignorelist = self.__readjson()  # 读取排除列表
            pagecourse = []
            for course in allcourse:
                courseurl = course.get_attribute('href')
                if courseurl not in ignorelist:
                    pagecourse.append(courseurl)
            if len(pagecourse) == 0:    # 如果这一页所有课程均不符合条件
                # 寻找下一页    i class="cd-icon cd-icon-arrow-right"
                nextpage:List[WebElement] = self.edge.find_elements_by_xpath('//i[@class="cd-icon cd-icon-arrow-right"]')
                if len(nextpage) == 0:
                    return None # 如果这一页没有适合的课程，又是最后一页，就返回 None
                nextpage[0].click()
                time.sleep(3)
            else:
                return pagecourse[0]

    def __checkurl(self, url:str) -> Union[str,bool]:
        '''检查课程是否为视频、阅读
        如果为答题则讲课程保存到忽略列表'''
        self.edge.get(url)  # 打开这个课程
        try:
            learnxpath = '//div[@class="text-right buy-btn-group visible-xs visible-sm"]/a'
            learn:WebElement = self.edge.find_element_by_xpath(learnxpath)
            self.edge.get(learn.get_attribute('href'))      # 开始学习
            condition_xpath = '//a[contains(@data-content,"满足以下条件")]'
            condition:WebElement = self.edge.find_element_by_xpath(condition_xpath)
            rule:str = condition.get_attribute('data-content')
        except:
            self.__updatejson(url)
            return False
        if '分钟' in rule or '学习到最后' in rule:
            return rule
        else:
            self.__updatejson(url)
            return False

    def __learn(self):
        '''开始在这个页面学习'''
        # 找到一个可以学习的网页
        while True:
            findurl = self.__findcourse()
            if isinstance(findurl, str):
                rule = self.__checkurl(findurl)
                if isinstance(rule, str):
                    break   # 找到了可以学习的网站
            else:
                return None # 已经学完了
        print(self.edge.title)
        if '分钟' in rule: # 阅读课程
            print('这是一个阅读任务')
            readtime = re.findall('\d+', rule)[0]
            readtime = int(readtime)
            print(f'学习 {readtime} 分钟')
            time.sleep(readtime*60+5)
            print('学习完成')
            return True
        elif '学习到最后' in rule:  # 视频课程
            print('这是视频任务')
            try:
                # 获取总时长
                # alltimebox:WebElement = self.edge.find_element_by_xpath('//div[@class="vjs-duration-display"]')
                # alltime = re.findall('\d+', alltimebox.text)
                # alltime = int(alltime[0])*60 + int(alltime[1]) - 3
                time.sleep(5)
                self.edge.switch_to.frame(self.edge.find_elements_by_xpath("//iframe")[0])
                self.edge.switch_to.frame(self.edge.find_elements_by_tag_name("iframe")[0])
                alltime = self.edge.execute_script('return document.getElementsByTagName("video")[0].duration')
                print(alltime)
                alltime = float(alltime)
                # document.getElementById('example_media_1_html5_api').duration
                #document.getElementById('playerId__4399364_html5_api').duration

                self.edge.execute_script(f'document.getElementsByTagName("video")[0].currentTime = {alltime-1};')
                time.sleep(10)
                print('视频任务完成')
                return True

            except Exception as e:
                # raise e
                self.__updatejson(findurl)
                return False
        else:
            self.__updatejson(findurl)
            return False

    def test(self):
        '''test'''
        try:
            '''try'''
            self.__login()
            while True:
                a = self.__learn()
                if a == None:
                    print('已经学完了')
                    break
                elif a == False:
                    print('不支持的任务类型，请手动观看')
                    continue



        except Exception as e:
            print(e)
            raise e
        finally:
            time.sleep(5)
            self.edge.quit()
        





if __name__ == '__main__':
    main()
